package fem2d;

import fem2.AbstractStructuralStaticDemo;
import fem2.Constraint;
import fem2.Element;
import fem2.Face;
import fem2.MaterialModel;
import fem2.Mesh;
import fem2.MeshGenerator;
import fem2.MeshPart;
import fem2.MeshUtilities;
import fem2.Model;
import fem2.Observer;
import fem2.element.StructuralElement;
import fem2.enu.State;
import fem2.material.ExponentialSofteningRule;
import fem2.material.FluencyCriteria;
import fem2.material.IsotropicDamageMM;
import fem2.material.StVenantKirchhoffMM;
import fem2.observer.GidDamageObserver;
import fem2.observer.TimeStepObserver;
import fem2.pre_and_post.GidMeshGenerator;
import fem2.strategies.Strategy;

/**
 * <pre>
 * Non-local damage mechanics with application to concrete
 * Milan Jirasek
 * </pre>
 * 
 * @author hbui
 * 
 */
public class ThreePointTestWithoutNotch_IsotropicDamage_FineMesh extends
		ThreePointTestWithoutNotch_IsotropicDamage {

	public ThreePointTestWithoutNotch_IsotropicDamage_FineMesh() {
		projectDir = "/home/hbui/kratos_janosch";
		projectName = "three-point-test-without-notch.gid";
		meshFileName = "quad-mesh-unstructure-fine.msh";
	}

	@Override
	public Mesh createMesh() {
		String fn = projectDir + '/' + projectName + '/' + meshFileName;
		MeshGenerator mg = new GidMeshGenerator(fn);
		Mesh mesh = mg.getMesh(2);

		return mesh;
	}

	@Override
	public Model createConditions(Model m) {
		Mesh mesh = m.getMesh();

		Constraint cxy = new Constraint(false, false);
		Constraint cy = new Constraint(true, false);

		MeshUtilities.seekNode(mesh, 0, 0).addConstraint(cxy);
		MeshUtilities.seekNode(mesh, 450, 0).addConstraint(cy);

		Constraint cu = new Constraint(true, false);
		cu.setValue(1, -0.1e-4);
		MeshUtilities.seekNodeNearest(mesh, 225, 100).addConstraint(cu);

		return m;
	}

	@Override
	public MaterialModel createMaterial(Model m) {
		double E = 20e9;
		double nu = 0.2;
		double t = 100;
		State ss = State.PLANE_STRESS;
		double e0 = 120e-6;
		double ef = 7e-3;
		FluencyCriteria softeningRule = new ExponentialSofteningRule(e0, ef);
		MaterialModel mm = new IsotropicDamageMM(E, nu, 0.0, t, ss, softeningRule, e0);
		return mm;
	}

	@Override
	public Element createElement(MeshPart mp, MaterialModel mm) {
		return new StructuralElement(mp, mm);
	}

	@Override
	public Model createModel() {
		Mesh mesh = createMesh();

		/*
		 * set the number of fields for structural problem
		 */
		mesh.setNumberOfFields(mesh.getDimension());

		Model m = new Model(mesh);

		MaterialModel mm = createMaterial(m);

		double E = 20e10;
		double nu = 0.2;
		double t = 100;
		State ss = State.PLANE_STRESS;
		MaterialModel mm2 = new StVenantKirchhoffMM(E, nu, t, 0, ss);

		int nf = mesh.countFaces();
		for (int i = 0; i < nf; i++) {
			Face f = mesh.getFace(i);
			double[] c = f.computeCenter();
			Element e;
			double r = Math.sqrt(Math.pow(c[0] - 225, 2) + Math.pow(c[1] - 110, 2));
			if (r > 15) {
				e = createElement(f, mm);
			} else {
				e = createElement(f, mm2);
			}
			m.addElement(e);
		}

		m = createConditions(m);

		return m;
	}

	@Override
	public void addObservers(Model m, Strategy s, TimeStepObserver o) {
		super.addObservers(m, s, o);

		if (meshFileName == null) {
			throw new Error("mesh file name was not set");
		}

		/*
		 * clean all previous post files
		 */
		String meshName = meshFileName.split("\\.")[0];

		Observer do1 = new GidDamageObserver(m, o, projectDir, projectName, meshName);
		s.addObserver(do1);

	}

	public static void main(String[] args) {
		AbstractStructuralStaticDemo demo = new ThreePointTestWithoutNotch_IsotropicDamage_FineMesh();

		demo.run(100);
	}
}
